/*
 ============================================================================
 Name		: P2PMessage.cpp
 Author	  : 
 Version	 : 1.0
 Copyright   : 
 Description : CP2PMessage implementation
 ============================================================================
 */

#include "P2PMessage.h"

#include <utf.h>

const TInt KAppIdMaxLength(8);
const TInt KMessageIdMaxLength(8);
const TInt KContentMaxLength(96);

CP2PMessage::CP2PMessage(TType aType) :
	iType( aType )
	{
	// No implementation required
	}

CP2PMessage::~CP2PMessage()
	{
	iAppId.Close();
	iMessageId.Close();
	iContent.Close();
	}

CP2PMessage* CP2PMessage::NewLC(TType aType,
		const TDesC8& aAppId,
		const TDesC8& aMessageId,
		const TDesC8& aContent,
		const TTime& aValidUntil)
	{
	CP2PMessage* self = new (ELeave) CP2PMessage(aType);
	CleanupStack::PushL(self);
	self->ConstructL(aAppId, aMessageId, aContent, aValidUntil);
	return self;
	}

CP2PMessage* CP2PMessage::NewL(TType aType,
		const TDesC8& aAppId,
		const TDesC8& aMessageId,
		const TDesC8& aContent,
		const TTime& aValidUntil)
	{
	CP2PMessage* self = CP2PMessage::NewLC(aType, aAppId, aMessageId, aContent, aValidUntil);
	CleanupStack::Pop(); // self;
	return self;
	}

void CP2PMessage::ConstructL(const TDesC8& aAppId,
		const TDesC8& aMessageId,
		const TDesC8& aContent,
		const TTime& aValidUntil)
	{
	iAppId.CreateL(aAppId.Right(KAppIdMaxLength) , KAppIdMaxLength);
	iMessageId.CreateL(aMessageId , KMessageIdMaxLength);
	iContent.CreateL(aContent , KContentMaxLength);
	iValidUntil = aValidUntil;
	}

const TDesC8& CP2PMessage::AppId() const
	{
	return iAppId;
	}

const TDesC8& CP2PMessage::MessageId() const
	{
	return iMessageId;
	}

const TDesC8& CP2PMessage::Content() const
	{
	return iContent;
	}

CP2PMessage::TType CP2PMessage::Type() const
	{
	return iType;
	}

void CP2PMessage::SetType(CP2PMessage::TType aType)
	{
	iType = aType;
	}

const TTime& CP2PMessage::ValidUntil() const
	{
	return iValidUntil;
	}

TBool CP2PMessage::IsValid() const
	{
	TTime nowUtc;
	nowUtc.UniversalTime();
	return nowUtc < iValidUntil;
	}

TInt CP2PMessage::ResponseMapOrder(const CP2PMessage& aA, const CP2PMessage& aB)
	{
	if (aA.iAppId < aB.iAppId)
		{
		return -1;
		}
	if (aA.iAppId > aB.iAppId)
		{
		return 1;
		}
	if (aA.iMessageId < aB.iMessageId)
		{
		return -1;
		}
	if (aA.iMessageId > aB.iMessageId)
		{
		return 1;
		}
	return 0;
	}

HBufC8* CP2PMessage::SerializeL()
	{
	HBufC8* result = HBufC8::NewL(4 + iAppId.Length() + iMessageId.Length() + iContent.Length());
	TPtr8 writable = result->Des();
	writable.FillZ(4);
	writable[0] = static_cast<char>(iType);
	writable[1] = iAppId.Length();
	writable[2] = iMessageId.Length();
	writable[3] = iContent.Length();
	writable.Append(iAppId);
	writable.Append(iMessageId);
	writable.Append(iContent);
	return result;
	}

HBufC8* CP2PMessage::ToJSON()
	{
	RBuf8 buffer;
	
	buffer.Create(500);
	buffer.Append(_L8("{\"type\":\""));
	switch (iType)
		{
		case EMessageToSend :
			buffer.Append(_L8("messageToSend"));
			break;
		case EResponseToSend :
			buffer.Append(_L8("responseToSend"));
			break;
		case EMessageSent :
			buffer.Append(_L8("messageSent"));
			break;
		case EResponseSent :
			buffer.Append(_L8("responseSent"));
			break;
		case EMessageReceived :
			buffer.Append(_L8("messageReceived"));
			break;
		case EResponseReceived :
			buffer.Append(_L8("responseReceived"));
			break;
		}
	buffer.Append(_L("\",\"appId\":\""));
	buffer.Append(iAppId);
	buffer.Append(_L("\",\"messageId\":\""));
	buffer.Append(iMessageId);
	buffer.Append(_L("\",\"content\":\""));
	buffer.Append(iContent);
	buffer.Append(_L("\"}"));
	
	HBufC8* result = buffer.Alloc();
	buffer.Close();
	return result;
	}

CP2PMessage* CP2PMessage::FromSerializedLC(const TDesC8& serialized)
	{
	static const TInt appIdStart(4);
	TType type = static_cast<TType>(serialized[0]);
	const TInt appIdLength = serialized[1];
	const TInt messageIdLength = serialized[2];
	const TInt contentLength = serialized[3];
	TPtrC8 appId = serialized.Mid(appIdStart, appIdLength);
	TPtrC8 messageId = serialized.Mid(appIdStart + appIdLength, messageIdLength);
	TPtrC8 content = serialized.Mid(appIdStart + appIdLength + messageIdLength, contentLength);
	return CP2PMessage::NewLC(type, appId, messageId, content, TTime());
	}
